;
(function($, $$) {

    $.fn.datePicker = function(options) {
        var self = this, args = Array.prototype.slice.call(arguments);
        args.push($$.DatePicker);
        var result = $$.createWidgetByJQuery.apply(self, args);
        if (result.jqObj !== undefined && options !== "widget") {
            return self;
        }
        return result;
    };

    $$.DatePicker = function(self, options) {
        if (!(this instanceof $$.DatePicker)) {
            return new $$.DatePicker(self, options);
        }
        var defaults = {

            datePickerClass : $$.defaultBorder + " uiCornerAll " + $$.defaultBoxShadow,

            titleClass : $$.defaultGradientBG + " uiCornerTop",

            date : null,

            weekViewArray : ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],

            monthViewArray : ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],

            dayClass : "",

            specialDayList : null,

            hoverClass : $$.hoverGradientBG,

            todayClass : $$.defaultGradientBG,

            defaultDateClass : "uiPurpleGradientBG",

            listClass : $$.defaultGradientBG + " uiBlueBorder uiCornerAll",

            listItemHoverClass : $$.hoverGradientBG,

            minDate : null,

            maxDate : null,

            tableWidth : 0,
            currentDate : null,
            dateObj : {
                year : null,
                month : null,
                day : null,
                week : null
            },
            origDateObj : null,
            minDateObj : null,
            maxDateObj : null,

            dateContainerHTML : '<div class="uiDateContainer"></div>',

            titleHTML : '<div class="uiTitle"><span class="uiPrevMonth uiArrowLeftIcon uiSmallIcon"></span><span class="uiMonthAndYear"><span class="uiMonth"><span></span></span><span class="uiYear"><span></span></span></span><span class="uiNextMonth uiArrowRightIcon uiSmallIcon"></span></div>',

            dayContainerHTML : '<div class="uiDayContainer"></div>',


            select : $.noop
        };
        var opts = $.extend(defaults, options);
        $$.DatePicker.prototype.superClass.call(this, self, opts);
        this.init();
    }
    $$.inherit($$.DatePicker, $$.Widget, {

        init : function() {
            var datePickerObj = this;
            datePickerObj.createWidget();
            initDatePicker(datePickerObj.jqObj, datePickerObj.opts);
            return datePickerObj;
        },

        setSpecialDayList : function(dayList) {
            var datePickerObj = this, self = datePickerObj.jqObj, opts = datePickerObj.opts;
            opts.specialDayList = dayList;
            if (checkView(dayList, opts.currentDate)) {
                setDate(self, opts);
            }
            return datePickerObj;
        },

        addSpecialDayList : function(dayList) {
            var datePickerObj = this, self = datePickerObj.jqObj, opts = datePickerObj.opts;
            datePickerObj.setSpecialDayList($.extend({}, opts.specialDayList, dayList));
            return datePickerObj;
        },

        removeSpecialDayList : function(key) {
            var datePickerObj = this, self = datePickerObj.jqObj, opts = datePickerObj.opts;
            if (opts.specialDayList === null) {
                return datePickerObj;
            }
            else if (key === undefined) {
                var tempDayList = opts.specialDayList;
                opts.specialDayList = null;
                if (checkView(tempDayList, opts.currentDate)) {
                    setDate(self, opts);
                }
            }
            else if (opts.specialDayList[key] !== undefined) {
                var dayList = {};
                dayList[key] = opts.specialDayList[key];
                opts.specialDayList[key] = null;
                delete opts.specialDayList[key];
                if (checkView(dayList, opts.currentDate)) {
                    setDate(self, opts);
                }
            }
            return datePickerObj;
        }
    });

    function initDatePicker(self, opts) {
        self.addClass("uiDatePicker uiWidget " + opts.datePickerClass);
        if (opts.dateStr !== null) {
            opts.currentDate = new Date(opts.dateStr);
            if (isNaN(opts.currentDate.getFullYear())) {
                opts.currentDate = new Date();
            }
            else {
                opts.origDateObj = {
                    year : opts.currentDate.getFullYear(),
                    month : opts.currentDate.getMonth(),
                    day : opts.currentDate.getDate()
                };
            }
        }
        else {
            opts.currentDate = new Date();
        }
        if (opts.min !== null) {
            var minDateObj = new Date(opts.min);
            if (!isNaN(minDateObj.getFullYear())) {
                opts.minDateObj = {
                    year : minDateObj.getFullYear(),
                    month : minDateObj.getMonth(),
                    day : minDateObj.getDate()
                };
            }
        }
        if (opts.max !== null) {
            var maxDateObj = new Date(opts.max);
            if (!isNaN(maxDateObj.getFullYear())) {
                opts.maxDateObj = {
                    year : maxDateObj.getFullYear(),
                    month : maxDateObj.getMonth(),
                    day : maxDateObj.getDate()
                };
            }
        }
        var dateContainer = $(opts.dateContainerHTML);
        var titleContainer = $(opts.titleHTML).addClass(opts.titleClass);
        var dayContainer = $(opts.dayContainerHTML);
        self.append(dateContainer.append(titleContainer).append(dayContainer));
        opts.weeksHTML = "<tr>";
        for (var i = 0; i < 7; i++) {
            opts.weeksHTML += ('<td class="uiWeekTD">' + opts.weekViewArray [i] + "</td>");
        }
        opts.weeksHTML += "</tr>";
        setDate(self, opts);

        var monthListHTML = '<ul class="uiMonthList ' + opts.listClass + '">';
        for (var i = 0, len = opts.monthViewArray.length; i < len; i++) {
            monthListHTML += ("<li>" + opts.monthViewArray[i] + "</li>");
        }
        monthListHTML += "</ul>";
        $("> .uiMonthAndYear > .uiMonth", titleContainer).append(monthListHTML);
        var yearListHTML = '<ul class="uiYearList ' + opts.listClass + '">';
        var currentYear = opts.currentDate.getFullYear();
        for (var i = 6; i > -6; i--) {
            yearListHTML += ("<li>" + (currentYear + i) + "</li>");
        }
        yearListHTML += "</ul>";
        $("> .uiMonthAndYear > .uiYear", titleContainer).append(yearListHTML);

        var isHidden = self.is(":hidden");
        if (isHidden) {
            self.show();
        }
        self.width($("> .uiDateContainer > .uiDayContainer > table", self).outerWidth(true) + parseInt($("> .uiDateContainer", self).css("marginLeft")) * 2);
        if (isHidden) {
            self.hide();
        }
        initEvent(self, opts);
        return self;
    }

    function initEvent(self, opts) {
        $(">.uiDateContainer >.uiDayContainer", self).bind({
            "mouseover.uiDatePicker" : function(e) {
                var target = $(e.target).parent();
                if (target.hasClass("uiNormalTD")) {
                    target.removeClass("uiNormalTD").addClass(opts.hoverClass);
                }
            },
            "mouseout.uiDatePicker" : function(e) {
                var target = $(e.target).parent();
                if (target.hasClass(opts.hoverClass)) {
                    target.removeClass(opts.hoverClass).addClass("uiNormalTD");
                }
            },
            "click.uiDatePicker" : function(e) {
                if (opts.disabled) {
                    return false;
                }
                var target = $(e.target).parent();
                if (target.hasClass("uiNormalTD") || target.hasClass(opts.hoverClass)) {
                    if (target.hasClass("disabled")) {
                        return false;
                    }
                    var monthStr = opts.dateObj.month + 1;
                    if (monthStr < 10) {
                        monthStr = "0" + monthStr;
                    }
                    var day = parseInt(target.text());
                    var dateStr = monthStr + "/" + day + "/" + opts.dateObj.year;
                    var dateObj = {
                        year : opts.dateObj.year,
                        month : opts.dateObj.month,
                        day : day
                    }
                    if ($.isFunction(opts.select)) {
                        opts.select.call(self[0], target, dateStr, dateObj, e);
                    }
                }
                $("> .uiDateContainer > .uiTitle", self).find(".uiMonthList, .uiYearList").hide();
            }
        });
        $(">.uiDateContainer >.uiTitle", self).click(function(e) {
            if (opts.disabled) {
                return false;
            }
            var target = $(e.target);
            if (target.hasClass("uiPrevMonth")) {
                opts.currentDate.setMonth(opts.currentDate.getMonth() - 1);
                setDate(self, opts, "prev");
            }
            else
            if (target.hasClass("uiNextMonth")) {
                opts.currentDate.setMonth(opts.currentDate.getMonth() + 1);
                setDate(self, opts, "next");
            }
            else
            if (target.parent().hasClass("uiMonth")) {
                target.siblings(".uiMonthList").slideToggle(opts.animateTime);
                $("> .uiDateContainer > .uiTitle", self).find(".uiYearList").hide();
                return false;
            }
            else
            if (target.parent().hasClass("uiYear")) {
                target.siblings(".uiYearList").slideToggle(opts.animateTime);
                $("> .uiDateContainer > .uiTitle", self).find(".uiMonthList").hide();
                return false;
            }
            else
            if (target.parent(".uiMonthList").length) {
                var month = $.inArray(target.text(), opts.monthViewArray);
                if (month !== -1) {
                    var status = "next";
                    var currentMonth = opts.currentDate.getMonth();
                    if (currentMonth !== month) {
                        if (currentMonth > month) {
                            status = "prev";
                        }
                        opts.currentDate.setMonth(month);
                        setDate(self, opts, status);
                    }
                }
                target.parent(".uiMonthList").hide();
                return false;
            }
            else
            if (target.parent(".uiYearList").length) {
                var year = parseInt(target.text());
                var currentYear = opts.currentDate.getFullYear();
                if (currentYear !== year) {
                    var status = "next";
                    target.siblings().andSelf().each(function(i) {
                        $(this).text(year + 6 - i);
                    });
                    if (currentYear > year) {
                        status = "prev";
                    }
                    opts.currentDate.setFullYear(year);
                    setDate(self, opts, status);
                }
                target.parent(".uiYearList").hide();
                return false;
            }
            $("> .uiDateContainer > .uiTitle", self).find(".uiMonthList, .uiYearList").hide();
        })
            .find(".uiMonthList").add($(">.uiDateContainer >.uiTitle .uiYearList", self)).bind({
                mousewheel : function(e, delta) {
                    if (delta < 0) {
                        $(this).children(":lt(6)").hide();
                    }
                    else {
                        $(this).children(":lt(6)").show();
                    }
                    return false;
                },
                mouseover : function(e) {
                    var target = $(e.target);
                    target.addClass(opts.listItemHoverClass);
                },
                mouseout : function(e) {
                    var target = $(e.target);
                    target.removeClass(opts.listItemHoverClass);
                }
            });
        self.bind("mousewheel.uiDatePicker", function(e, delta) {
            if (delta < 0) {
                $(">.uiDateContainer >.uiTitle >.uiNextMonth", this).click();
            }
            else {
                $(">.uiDateContainer >.uiTitle >.uiPrevMonth", this).click();
            }
            return false;
        });
        return self;
    }

    function setDate(self, opts, status) {
        opts.dateObj.year = opts.currentDate.getFullYear();
        opts.dateObj.month = opts.currentDate.getMonth();
        opts.dateObj.day = opts.currentDate.getDate();
        opts.dateObj.week = opts.currentDate.getDay();

        var today = new Date();
        var todayObj = {
            year : today.getFullYear(),
            month : today.getMonth(),
            day : today.getDate()
        }
        var todayFlag = false;
        var origDateFlag = false;
        var checkMinDate = false;
        var minDateFlag = false;
        var checkMaxDate = false;
        var maxDateFlag = false;
        var html = '<table cellspacing="0" cellpadding="0"><tbody>';
        var firstDayWeek = (opts.dateObj.week - opts.dateObj.day + 36) % 7;
        var dayContainer = $(">.uiDateContainer >.uiDayContainer", self);
        var titleContainer = $(">.uiDateContainer >.uiTitle", self);

        var monthStr = opts.dateObj.month + 1;
        if (monthStr < 10) {
            monthStr = "0" + monthStr;
        }

        if (todayObj.year === opts.dateObj.year && todayObj.month === opts.dateObj.month) {
            todayFlag = true;
        }
        if (opts.minDateObj !== null) {
            if (opts.minDateObj.year > opts.dateObj.year || (opts.minDateObj.year === opts.dateObj.year && opts.minDateObj.month > opts.dateObj.month)) {
                minDateFlag = true;
            }
            else
            if (opts.minDateObj.year === opts.dateObj.year && opts.minDateObj.month === opts.dateObj.month) {
                checkMinDate = true;
            }
        }
        else {
            checkMinDate = false;
        }
        if (opts.maxDateObj !== null) {
            if (opts.maxDateObj.year < opts.dateObj.year || (opts.maxDateObj.year === opts.dateObj.year && opts.maxDateObj.month < opts.dateObj.month)) {
                maxDateFlag = true;
            }
            else
            if (opts.maxDateObj.year === opts.dateObj.year && opts.maxDateObj.month === opts.dateObj.month) {
                checkMaxDate = true;
            }
        }
        else {
            checkMaxDate = false;
        }

        if (opts.origDateObj !== null) {
            if (opts.origDateObj.year === opts.dateObj.year && opts.origDateObj.month === opts.dateObj.month) {
                origDateFlag = true;
            }
        }
        titleContainer.find("> .uiMonthAndYear > .uiMonth > span:first").html(opts.monthViewArray[opts.dateObj.month]).end().find("> .uiMonthAndYear > .uiYear > span:first").html(opts.dateObj.year);
        html += opts.weeksHTML;
        var total = 30;
        if (opts.dateObj.month === 1) {
            total = 28;
            if (opts.dateObj.year % 400 === 0 || (opts.dateObj.year % 4 === 0 && opts.dateObj.year % 100 !== 0)) {
                total = 29;
            }
        }
        else
        if (opts.dateObj.month % 2 === 0) {
            total = 31;
        }
        var day = 1;
        var totalTD = Math.ceil((total + firstDayWeek) / 7) * 7;
        for (var i = 0; i < totalTD; i++) {
            if (i % 7 === 0) {
                html += "<tr>";
            }
            if (i < firstDayWeek || day > total) {
                html += ("<td></td>");
            }
            else {
                var dayStr = day;
                if (dayStr < 10) {
                    dayStr = "0" + dayStr;
                }
                var tdClass = "uiNormalTD " + opts.dayClass;
                if (todayFlag && day === todayObj.day) {
                    tdClass += " uiTodayTD " + opts.todayClass;
                }
                else
                if (origDateFlag && day === opts.origDateObj.day) {
                    tdClass += " uiTodayTD " + opts.originalDateClass;
                }
                var dayClass = "";
                var title = "";
                if (opts.specialDayList !== null) {
                    var dateStr = monthStr + "/" + dayStr + "/" + opts.dateObj.year;
                    if (opts.specialDayList[dateStr] !== undefined) {
                        dayClass = opts.specialDayList[dateStr].specialClass;
                        title = opts.specialDayList[dateStr].desc;
                    }
                }
                if ((minDateFlag || (checkMinDate && day < opts.minDateObj.day)) || (maxDateFlag || (checkMaxDate && day > opts.maxDateObj.day))) {
                    tdClass += " disabled";
                }
                html += ('<td class="' + tdClass + '"><div class="' + dayClass + '" title="' + title + '">' + dayStr + "</div></td>");
                day++;
            }
            if (i % 7 === 6) {
                html += "</tr>";
            }
        }
        html += '</tbody></table>';
        var newTable = $(html);
        if (status === undefined) {
            dayContainer.empty().append(newTable);
        }
        else
        if (status === "prev") {
            if (opts.tableWidth === 0) {
                opts.tableWidth = $(">.uiDateContainer >.uiDayContainer >table", self).outerWidth(true);
            }
            var oldTalbe = dayContainer.children("table");
            dayContainer.prepend(newTable.css("marginLeft", -opts.tableWidth));
            newTable.animate({marginLeft : 0}, opts.animateTime, function() {
                oldTalbe.remove();
            });
        }
        else {
            if (opts.tableWidth === 0) {
                opts.tableWidth = $(">.uiDateContainer >.uiDayContainer >table", self).outerWidth(true);
            }
            var oldTalbe = dayContainer.children("table");
            dayContainer.append(newTable);
            oldTalbe.animate({marginLeft : -opts.tableWidth}, opts.animateTime, function() {
                oldTalbe.remove();
            });
        }
        return self;
    }

    function checkView(dayList, currentDate) {
        var view = false;
        var year = currentDate.getFullYear();
        var month = currentDate.getMonth() + 1;

        $.each(dayList, function(key, value) {
            var dateArr = key.split("/");
            if (parseInt(dateArr[0]) == month && dateArr[2] == year) {
                view = true;
                return false;
            }
        });
        return view;
    }
})(jQuery, BASE);